package com.ithuang.quartz.utils;

import com.ithuang.quartz.domain.SysJob;
import org.apache.commons.lang3.StringUtils;
import org.quartz.JobExecutionContext;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;

import static com.ithuang.quartz.constant.ScheduleConstants.TASK_PARAMS;

/**
 * 执行定时任务的方法
 * @author HTT
 */
public class JobExecuteUtils {

    public static void main(String args[]){

    }
    /**
     * 获取bean并执行对应的方法
     * @param jobExecutionContext
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public static void executeMethod(JobExecutionContext jobExecutionContext) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Object param = jobExecutionContext.getMergedJobDataMap().get(TASK_PARAMS);
        SysJob sysJob = new SysJob();
        BeanUtils.copyProperties(param,sysJob);
        Object bean = SpringUtils.getBean(sysJob.getBeanTarget());
        List<Object[]> methodParams = getMethodParams(sysJob.getParams());
        if(SpringUtils.isNotNull(methodParams) && methodParams.size() > 0){
            Method method = bean.getClass().getMethod(sysJob.getBeanMethodTarget(),getMethodParamsType(methodParams));
            method.invoke(bean,getMethodParamsValue(methodParams));
        }else {
            Method method = bean.getClass().getMethod(sysJob.getBeanMethodTarget());
            method.invoke(bean);
        }

    }

    /**
     * 获取参数值
     *
     * @param methodParams 参数相关列表
     * @return 参数值列表
     */
    public static Object[] getMethodParamsValue(List<Object[]> methodParams)
    {
        Object[] classs = new Object[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams)
        {
            classs[index] = (Object) os[0];
            index++;
        }
        return classs;
    }

    /**
     * 获取参数类型
     *
     * @param methodParams 参数相关列表
     * @return 参数类型列表
     */
    public static Class<?>[] getMethodParamsType(List<Object[]> methodParams)
    {
        Class<?>[] classs = new Class<?>[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams)
        {
            classs[index] = (Class<?>) os[1];
            index++;
        }
        return classs;
    }

    /**
     * 获取method方法参数相关列表
     *
     * @param params 目标字符串
     * @return method方法相关参数列表
     */
    public static List<Object[]> getMethodParams(String params)
    {
        if (StringUtils.isEmpty(params))
        {
            return null;
        }
        String[] methodParams = params.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)");
        List<Object[]> classs = new LinkedList<>();
        for (int i = 0; i < methodParams.length; i++)
        {
            String str = StringUtils.trimToEmpty(methodParams[i]);
            // String字符串类型，以'或"开头
            if (StringUtils.startsWithAny(str, "'", "\""))
            {
                classs.add(new Object[] { StringUtils.substring(str, 1, str.length() - 1), String.class });
            }
            // boolean布尔类型，等于true或者false
            else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str))
            {
                classs.add(new Object[] { Boolean.valueOf(str), Boolean.class });
            }
            // long长整形，以L结尾
            else if (StringUtils.endsWith(str, "L"))
            {
                classs.add(new Object[] { Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class });
            }
            // double浮点类型，以D结尾
            else if (StringUtils.endsWith(str, "D"))
            {
                classs.add(new Object[] { Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class });
            }
            // 其他类型归类为整形
            else
            {
                classs.add(new Object[] { Integer.valueOf(str), Integer.class });
            }
        }
        return classs;
    }

}
